<?php

namespace Swocloud;

use Swoole\Server as SwooleServer;

abstract class Server
{
    protected $swooleServer;

    protected $port = 9100;

    protected $host = '0.0.0.0';

    protected $rootPath = '';

    // 用户配置文件
    protected $config;

    protected $swooleConfig = [
        'task_worker_num' => 0
    ];

    /**
     * pid记录文件地址
     * @var string
     */
    protected $pidFile = '/runtime/swoole.pid';

    protected $pidMap = [
        'masterPid' => 0,   // 主进程id
        'managerPid' => 0,  // 管理进程id
        'workerPids' => [], // 工作进程id
        'taskPids' => []    // 任务进程id
    ];

    protected $events = [
        // 基础方法
        'server' => [
            'start'        => 'onStart',
            'shutdown'     => 'onShutdown',
            'workerStart'  => 'onWorkerStart',
            'workerStop'   => 'onWorkerStop',
            'workerExit'   => 'onWorkerExit',
            'connect'      => 'onConnect',
            'close'        => 'onClose',
            'workerError'  => 'onWorkerError',
            'managerStart' => 'onManagerStart',
            'managerStop'  => 'onManagerStop',
        ],
        // 子类方法
        'sub' => [],
        // 额外方法
        'ext' => []
    ];

    public function __construct()
    {
        // 读取配置文件
        $this->initConfig();
        // 创建server
        $this->createServer();
        // 设置需要注册的回调函数
        $this->initEvents();
        // 设置swoole的回调函数
        $this->setSwooleEvents();
        // 设置swoole配置信息
        $this->swooleServer->set($this->swooleConfig);
    }

    public function start($rootPath)
    {
        $this->rootPath = $rootPath;
        // 服务启动
        $this->swooleServer->start();
    }

    /**
     * 创建服务
     * @return mixed 
     */
    abstract protected function createServer();

    /**
     * 初始化事件
     * @return mixed 
     */
    abstract protected function initEvents();

    /**
     * 配置初始化
     * @return void 
     */
    protected function initConfig()
    {
        $config = include $this->rootPath . 'config/server.php';
        $this->config = $config;

        $this->host = !empty($config['host']) ? $config['host'] : $this->host;
        $this->port = !empty($config['port']) ? $config['port'] : $this->port;
        $this->swooleConfig = !empty($config['swoole']) ? $config['swoole'] : $this->swooleConfig;
    }

    /**
     * 绑定swoole回调函数
     * @return void 
     */
    protected function setSwooleEvents()
    {
        foreach ($this->events as $type => $events) {
            foreach ($events as $event => $function) {
                $this->swooleServer->on($event, [$this, $function]);
            }
        }
    }

    protected function setEvent($type, $event)
    {
        if ($type == 'server') {
            return $this;
        }

        $this->events[$type] = $event;
        return $this;
    }

    /**
     * 获取配置
     * @return array 
     */
    public function getConfig(): array
    {
        return $this->swooleConfig;
    }

    /**
     * 设置配置
     * @param mixed $config 
     * @return $this 
     */
    public function setConfig($config)
    {
        $this->swooleConfig = array_map($this->swooleConfig, $config);
        return $this;
    }

    public function onStart(SwooleServer $server)
    {
    }

    public function onShutdown()
    {
    }

    public function onWorkerStart(SwooleServer $server, int $workerId)
    {
    }

    public function onWorkerStop()
    {
    }

    public function onWorkerExit()
    {
    }

    public function onConnect()
    {
    }

    public function onClose($server, $fd)
    {
    }

    public function onWorkerError()
    {
    }

    public function onManagerStart()
    {
    }

    public function onManagerStop()
    {
    }
}
